home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / triv_lib / triv_sub.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  9KB  |  243 lines

  1. /******************************************************************************
  2. * Triv_Sub.c - Computes subdivision of tri-variates.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Sep. 94.                          *
  5. ******************************************************************************/
  6.  
  7. #include "triv_loc.h"
  8.  
  9. /*****************************************************************************
  10. * DESCRIPTION:                                                               M
  11. * Given a tri-variate, subdivides it at parameter value t in direction         M
  12. * Dir.                                         M
  13. *                                                                            *
  14. * PARAMETERS:                                                                M
  15. *   TV:       Trivariate to subdivide.                                       M
  16. *   t:        Parameter to subdivide at.                                     M
  17. *   Dir:      Direction of subdivision.                                      M
  18. *                                                                            *
  19. * RETURN VALUE:                                                              M
  20. *   TrivTVStruct *:   A list of two trivariates, result of the subdivision.  M
  21. *                                                                            *
  22. * KEYWORDS:                                                                  M
  23. *   TrivTVSubdivAtParam, trivariates                                         M
  24. *****************************************************************************/
  25. TrivTVStruct *TrivTVSubdivAtParam(TrivTVStruct *TV,
  26.                   CagdRType t,
  27.                   TrivTVDirType Dir)
  28. {
  29.     int i, j, KVLen, Index1, Index2, Mult,
  30.     UOrder = TV -> UOrder,
  31.     VOrder = TV -> VOrder,
  32.     WOrder = TV -> WOrder,
  33.     ULength = TV -> ULength,
  34.     VLength = TV -> VLength,
  35.     WLength = TV -> WLength;
  36.     CagdRType *RefKV;
  37.     CagdSrfStruct *Srf, *LSrf, *RSrf;
  38.     TrivTVStruct *RTV, *LTV;
  39.  
  40.     if (TRIV_IS_BEZIER_TV(TV)) {
  41.     RTV = TrivBzrTVNew(ULength, VLength, WLength, TV -> PType);
  42.     LTV = TrivBzrTVNew(ULength, VLength, WLength, TV -> PType);
  43.     }
  44.     else if (TRIV_IS_BSPLINE_TV(TV)) {
  45.     switch (Dir) {
  46.         case TRIV_CONST_U_DIR:
  47.         RefKV = TV -> UKnotVector;
  48.         KVLen = UOrder + ULength;
  49.         Index1 = BspKnotLastIndexL(RefKV, KVLen, t);
  50.         if (Index1 + 1 < UOrder)
  51.             Index1 = UOrder - 1;
  52.         Index2 = BspKnotFirstIndexG(RefKV, KVLen, t);
  53.         if (Index2 > ULength)
  54.             Index2 = ULength;
  55.         LTV = TrivBspTVNew(Index1 + 1, VLength, WLength,
  56.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  57.                    TV -> PType);
  58.         RTV = TrivBspTVNew(ULength - Index2 + UOrder, VLength, WLength,
  59.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  60.                    TV -> PType);
  61.         Mult = UOrder - 1 - (Index2 - Index1 - 1);
  62.  
  63.         /* Update the new knot vectors. */
  64.         CAGD_GEN_COPY(LTV -> UKnotVector,
  65.                   TV -> UKnotVector,
  66.                   sizeof(CagdRType) * (Index1 + 1));
  67.         /* Close the knot vector with multiplicity Order: */
  68.         for (j = Index1 + 1; j <= Index1 + UOrder; j++)
  69.             LTV -> UKnotVector[j] = t;
  70.         CAGD_GEN_COPY(&RTV -> UKnotVector[UOrder],
  71.                   &TV -> UKnotVector[Index2],
  72.                   sizeof(CagdRType) *
  73.                   (ULength + UOrder - Index2));
  74.         /* Make sure knot vector starts with multiplicity Order: */
  75.         for (j = 0; j < UOrder; j++)
  76.             RTV -> UKnotVector[j] = t;
  77.         
  78.         /* And copy the other direction knot vectors. */
  79.         CAGD_GEN_COPY(LTV -> VKnotVector,
  80.                   TV -> VKnotVector,
  81.                   sizeof(CagdRType) * (VOrder + VLength));
  82.         CAGD_GEN_COPY(RTV -> VKnotVector,
  83.                   TV -> VKnotVector,
  84.                   sizeof(CagdRType) * (VOrder + VLength));
  85.         CAGD_GEN_COPY(LTV -> WKnotVector,
  86.                   TV -> WKnotVector,
  87.                   sizeof(CagdRType) * (WOrder + WLength));
  88.         CAGD_GEN_COPY(RTV -> WKnotVector,
  89.                   TV -> WKnotVector,
  90.                   sizeof(CagdRType) * (WOrder + WLength));
  91.         break;
  92.         case TRIV_CONST_V_DIR:
  93.         RefKV = TV -> VKnotVector;
  94.         KVLen = VOrder + VLength;
  95.         Index1 = BspKnotLastIndexL(RefKV, KVLen, t);
  96.         if (Index1 + 1 < VOrder)
  97.             Index1 = VOrder - 1;
  98.         Index2 = BspKnotFirstIndexG(RefKV, KVLen, t);
  99.         if (Index2 > VLength)
  100.             Index2 = VLength;
  101.         LTV = TrivBspTVNew(ULength, Index1 + 1, WLength,
  102.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  103.                    TV -> PType);
  104.         RTV = TrivBspTVNew(ULength, VLength - Index2 + VOrder, WLength,
  105.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  106.                    TV -> PType);
  107.         Mult = VOrder - 1 - (Index2 - Index1 - 1);
  108.  
  109.         /* Update the new knot vectors. */
  110.         CAGD_GEN_COPY(LTV -> VKnotVector,
  111.                   TV -> VKnotVector,
  112.                   sizeof(CagdRType) * (Index1 + 1));
  113.         /* Close the knot vector with multiplicity Order: */
  114.         for (j = Index1 + 1; j <= Index1 + VOrder; j++)
  115.             LTV -> VKnotVector[j] = t;
  116.         CAGD_GEN_COPY(&RTV -> VKnotVector[VOrder],
  117.                   &TV -> VKnotVector[Index2],
  118.                   sizeof(CagdRType) *
  119.                   (VLength + VOrder - Index2));
  120.         /* Make sure knot vector starts with multiplicity Order: */
  121.         for (j = 0; j < VOrder; j++)
  122.             RTV -> VKnotVector[j] = t;
  123.         
  124.         /* And copy the other direction knot vectors. */
  125.         CAGD_GEN_COPY(LTV -> UKnotVector,
  126.                   TV -> UKnotVector,
  127.                   sizeof(CagdRType) * (UOrder + ULength));
  128.         CAGD_GEN_COPY(RTV -> UKnotVector,
  129.                   TV -> UKnotVector,
  130.                   sizeof(CagdRType) * (UOrder + ULength));
  131.         CAGD_GEN_COPY(LTV -> WKnotVector,
  132.                   TV -> WKnotVector,
  133.                   sizeof(CagdRType) * (WOrder + WLength));
  134.         CAGD_GEN_COPY(RTV -> WKnotVector,
  135.                   TV -> WKnotVector,
  136.                   sizeof(CagdRType) * (WOrder + WLength));
  137.         break;
  138.         case TRIV_CONST_W_DIR:
  139.         RefKV = TV -> WKnotVector;
  140.         KVLen = WOrder + WLength;
  141.         Index1 = BspKnotLastIndexL(RefKV, KVLen, t);
  142.         if (Index1 + 1 < WOrder)
  143.             Index1 = WOrder - 1;
  144.         Index2 = BspKnotFirstIndexG(RefKV, KVLen, t);
  145.         if (Index2 > WLength)
  146.             Index2 = WLength;
  147.         LTV = TrivBspTVNew(ULength, VLength, Index1 + 1,
  148.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  149.                    TV -> PType);
  150.         RTV = TrivBspTVNew(ULength, VLength, WLength - Index2 + WOrder,
  151.                    TV -> UOrder, TV -> VOrder, TV -> WOrder,
  152.                    TV -> PType);
  153.         Mult = WOrder - 1 - (Index2 - Index1 - 1);
  154.  
  155.         /* Update the new knot vectors. */
  156.         CAGD_GEN_COPY(LTV -> WKnotVector,
  157.                   TV -> WKnotVector,
  158.                   sizeof(CagdRType) * (Index1 + 1));
  159.         /* Close the knot vector with multiplicity Order: */
  160.         for (j = Index1 + 1; j <= Index1 + WOrder; j++)
  161.             LTV -> WKnotVector[j] = t;
  162.         CAGD_GEN_COPY(&RTV -> WKnotVector[WOrder],
  163.                   &TV -> WKnotVector[Index2],
  164.                   sizeof(CagdRType) *
  165.                   (WLength + WOrder - Index2));
  166.         /* Make sure knot vector starts with multiplicity Order: */
  167.         for (j = 0; j < WOrder; j++)
  168.             RTV -> WKnotVector[j] = t;
  169.         
  170.         /* And copy the other direction knot vectors. */
  171.         CAGD_GEN_COPY(LTV -> UKnotVector,
  172.                   TV -> UKnotVector,
  173.                   sizeof(CagdRType) * (UOrder + ULength));
  174.         CAGD_GEN_COPY(RTV -> UKnotVector,
  175.                   TV -> UKnotVector,
  176.                   sizeof(CagdRType) * (UOrder + ULength));
  177.         CAGD_GEN_COPY(LTV -> VKnotVector,
  178.                   TV -> VKnotVector,
  179.                   sizeof(CagdRType) * (VOrder + VLength));
  180.         CAGD_GEN_COPY(RTV -> VKnotVector,
  181.                   TV -> VKnotVector,
  182.                   sizeof(CagdRType) * (VOrder + VLength));
  183.         break;
  184.         default:
  185.         TRIV_FATAL_ERROR(TRIV_ERR_DIR_NOT_VALID);
  186.         RTV = LTV = NULL;
  187.         break;
  188.     }
  189.     }
  190.     else {
  191.     TRIV_FATAL_ERROR(TRIV_ERR_UNDEF_TRIVAR);
  192.     return NULL;
  193.     }
  194.  
  195.     switch (Dir) {
  196.     case TRIV_CONST_U_DIR:
  197.         for (i = 0; i < WLength; i++) {
  198.         Srf = TrivSrfFromMesh(TV, i, TRIV_CONST_W_DIR);
  199.         LSrf = CagdSrfSubdivAtParam(Srf, t, CAGD_CONST_U_DIR);
  200.         RSrf = LSrf -> Pnext;
  201.         TrivSrfToMesh(LSrf, i, TRIV_CONST_W_DIR, LTV);
  202.         TrivSrfToMesh(RSrf, i, TRIV_CONST_W_DIR, RTV);
  203.  
  204.         CagdSrfFree(Srf);
  205.         CagdSrfFree(LSrf);
  206.         CagdSrfFree(RSrf);
  207.         }
  208.         break;
  209.     case TRIV_CONST_V_DIR:
  210.         for (i = 0; i < ULength; i++) {
  211.         Srf = TrivSrfFromMesh(TV, i, TRIV_CONST_U_DIR);
  212.         LSrf = CagdSrfSubdivAtParam(Srf, t, CAGD_CONST_U_DIR);
  213.         RSrf = LSrf -> Pnext;
  214.         TrivSrfToMesh(LSrf, i, TRIV_CONST_U_DIR, LTV);
  215.         TrivSrfToMesh(RSrf, i, TRIV_CONST_U_DIR, RTV);
  216.  
  217.         CagdSrfFree(Srf);
  218.         CagdSrfFree(LSrf);
  219.         CagdSrfFree(RSrf);
  220.         }
  221.         break;
  222.     case TRIV_CONST_W_DIR:
  223.         for (i = 0; i < ULength; i++) {
  224.         Srf = TrivSrfFromMesh(TV, i, TRIV_CONST_U_DIR);
  225.         LSrf = CagdSrfSubdivAtParam(Srf, t, CAGD_CONST_V_DIR);
  226.         RSrf = LSrf -> Pnext;
  227.         TrivSrfToMesh(LSrf, i, TRIV_CONST_U_DIR, LTV);
  228.         TrivSrfToMesh(RSrf, i, TRIV_CONST_U_DIR, RTV);
  229.  
  230.         CagdSrfFree(Srf);
  231.         CagdSrfFree(LSrf);
  232.         CagdSrfFree(RSrf);
  233.         }
  234.         break;
  235.     default:
  236.         TRIV_FATAL_ERROR(TRIV_ERR_DIR_NOT_CONST_UVW);
  237.         break;
  238.     }
  239.  
  240.     LTV -> Pnext = RTV;
  241.     return LTV;
  242. }
  243.